// 文件路径: src/main/java/org/example/demo/CheckAllSqlsInFileAction.java
package org.example.demo;

import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlText;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public class CheckAllSqlsInFileAction extends AnAction {

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Project project = e.getProject();
        VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
        if (project == null || virtualFile == null || !virtualFile.exists()) {
            Messages.showMessageDialog(project, "项目或文件不存在", "SQL 批量检查", Messages.getErrorIcon());
            return;
        }

        // 获取 PsiFile
        PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
        if (!(psiFile instanceof XmlFile)) {
            Messages.showMessageDialog(project, "仅支持 XML 文件", "SQL 批量检查", Messages.getErrorIcon());
            return;
        }

        // ✅ 在 ReadAction 中处理 PSI
        ReadAction.run(() -> {
            List<SqlCheckResult> results = new ArrayList<>();
            XmlTag rootTag = ((XmlFile) psiFile).getRootTag();

            if (rootTag == null) return;

            // 查找所有 select/update/insert/delete 标签
            Arrays.stream(new String[]{"select", "update", "insert", "delete"})
                    .forEach(tagName -> {
                        XmlTag[] tags = rootTag.findSubTags(tagName, null);
                        for (XmlTag tag : tags) {
                            checkSqlTag(tag, results);
                        }
                    });

            // 显示汇总结果
            showBatchResultDialog(project, results, psiFile.getName());
        });
    }

    private void checkSqlTag(XmlTag tag, List<SqlCheckResult> results) {
        XmlText[] content = PsiTreeUtil.getChildrenOfType(tag, XmlText.class);
        if (content == null || content.length == 0) {
            results.add(new SqlCheckResult(tag.getName(), tag.getValue().getText(), "EMPTY", null));
            return;
        }

        String sql = content[0].getValue().trim();
        if (sql.isEmpty()) {
            results.add(new SqlCheckResult(tag.getName(), sql, "EMPTY", null));
            return;
        }

        String error = SqlValidator.validate(sql);
        results.add(new SqlCheckResult(tag.getName(), sql, error, null));
    }

    private void showBatchResultDialog(Project project, List<SqlCheckResult> results, String fileName) {
        StringBuilder msg = new StringBuilder();
        msg.append("📊 文件: ").append(fileName).append("\n");
        msg.append("🔍 共扫描 ").append(results.size()).append(" 条 SQL 语句\n\n");

        AtomicInteger validCount = new AtomicInteger();
        List<SqlCheckResult> failed = new ArrayList<>();

        for (SqlCheckResult r : results) {
            if (r.error == null) {
                validCount.incrementAndGet();
            } else if (!"EMPTY".equals(r.error)) {
                failed.add(r);
            }
        }

        msg.append("✅ 语法正确: ").append(validCount.get()).append("\n");
        msg.append("❌ 语法错误: ").append(failed.size()).append("\n");
        msg.append("➖ 空语句: ").append((int) results.stream().filter(r -> "EMPTY".equals(r.error)).count())
           .append("\n\n");

        if (!failed.isEmpty()) {
            msg.append("🔴 错误详情:\n");
            failed.forEach(r -> msg.append("  [").append(r.type.toUpperCase()).append("] ")
                    .append(r.error).append("\n"));
            msg.append("\n");
        }

        // 是否执行所有合法 SQL？
        if (validCount.get() > 0) {
            int choice = Messages.showYesNoCancelDialog(
                    project,
                    msg.toString() + "\n是否执行所有语法正确的 SQL？（#{xxx} 将替换为 '-1'）",
                    "批量 SQL 检查结果",
                    "执行所有", "仅查看", "取消",
                    Messages.getInformationIcon()
            );

            if (choice == Messages.YES) {
                executeValidSqls(project, results);
            } else if (choice == Messages.NO) {
                // 仅查看，不执行
                Messages.showMessageDialog(project, msg.toString(), "批量检查结果", Messages.getInformationIcon());
            }
        } else {
            Messages.showMessageDialog(project, msg.toString(), "批量检查结果", Messages.getInformationIcon());
        }
    }

    private void executeValidSqls(Project project, List<SqlCheckResult> results) {
        StringBuilder log = new StringBuilder();
        log.append("🚀 开始执行 ").append(results.size()).append(" 条合法 SQL\n\n");

        for (SqlCheckResult r : results) {
            if (r.error != null) continue;

            String parsedSql = r.sql.replaceAll("\\#\\{[^}]+\\}", "'-1'").trim();
            SqlExecutor.Result result = SqlExecutor.execute(project, parsedSql);

            log.append("📌 [").append(r.type.toUpperCase()).append("]\n");
            log.append("SQL: ").append(parsedSql).append("\n");

            if (result.success) {
                log.append("✅ 成功 | 耗时: ").append(result.duration).append("ms");
                if (result.isQuery) {
                    log.append(" | 返回 ").append(result.rows.size()).append(" 行\n");
                } else {
                    log.append(" | 影响 ").append(result.affectedRows).append(" 行\n");
                }
            } else {
                log.append("❌ 失败 | ").append(result.message).append("\n");
            }
            log.append("\n");
        }

        Messages.showMessageDialog(project, log.toString(), "批量执行结果", null);
    }

    @Override
    public void update(@NotNull AnActionEvent e) {
        VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);
        boolean enabled = file != null && file.getName().toLowerCase().endsWith(".xml");
        e.getPresentation().setEnabled(enabled);
        e.getPresentation().setText("Check All SQLs in File");
    }

    // 内部类：存储每条 SQL 的检查结果
    public static class SqlCheckResult {
        final String type;
        final String sql;
        final String error;
        final String location;

        public SqlCheckResult(String type, String sql, String error, String location) {
            this.type = type;
            this.sql = sql;
            this.error = error;
            this.location = location;
        }
    }
}